(function ($) {
    // 当domReady的时候开始初始化
    $(function () {
        const $wrap = $("#uploader");

        // 图片容器
        const $queue = $('<ul class="filelist"></ul>').appendTo($wrap.find(".queueList"));

        // 状态栏，包括进度和控制按钮
        const $statusBar = $wrap.find(".statusBar");

        // 文件总体选择信息。
        const $info = $statusBar.find(".info");

        // 上传按钮
        const $upload = $(".uploadBtn");

        // 没选择文件之前的内容。
        const $placeHolder = $wrap.find(".placeholder");

        const $progress = $statusBar.find(".progress").hide();

        // 添加的文件数量
        let fileCount = 0;

        // 添加的文件总大小
        let fileSize = 0;

        // 优化retina, 在retina下这个值是2
        const ratio = window.devicePixelRatio || 1;

        // 缩略图大小
        const thumbnailWidth = 110 * ratio;
        const thumbnailHeight = 110 * ratio;

        // 可能有pedding, ready, uploading, confirm, done.
        // let state = "pedding";

        // 所有文件的进度信息，key为file id
        const percentages = {};
        // 判断浏览器是否支持图片的base64
        const isSupportBase64 = (function () {
            const data = new Image();
            let support = true;
            data.onload = data.onerror = function () {
                if (this.width != 1 || this.height != 1) {
                    support = false;
                }
            };
            data.src = "";
            return support;
        })();

        // 检测是否已经安装flash，检测flash的版本
        const flashVersion = (function () {
            let version;

            try {
                version = navigator.plugins["Shockwave Flash"];
                version = version.description;
            } catch (ex) {
                try {
                    version = new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");
                } catch (ex2) {
                    version = "0.0";
                }
            }
            version = version.match(/\d+/g);
            return parseFloat(version[0] + "." + version[1], 10);
        })();

        const supportTransition = (function () {
            let s = document.createElement("p").style;
            const r = "transition" in s || "WebkitTransition" in s || "MozTransition" in s || "msTransition" in s || "OTransition" in s;
            s = null;
            return r;
        })();

        // WebUploader实例
        // let uploader;

        if (!WebUploader.Uploader.support("flash") && WebUploader.browser.ie) {
            // flash 安装了但是版本过低。
            if (flashVersion) {
                (function (container) {
                    window["expressinstallcallback"] = function (state) {
                        switch (state) {
                            case "Download.Cancelled":
                                alert("您取消了更新！");
                                break;

                            case "Download.Failed":
                                alert("安装失败");
                                break;

                            default:
                                alert("安装已成功，请刷新！");
                                break;
                        }
                        delete window["expressinstallcallback"];
                    };

                    const swf = "./expressInstall.swf";
                    // insert flash object
                    let html = '<object type="application/' + 'x-shockwave-flash" data="' + swf + '" ';

                    if (WebUploader.browser.ie) {
                        html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
                    }

                    html += 'width="100%" height="100%" style="outline:0">' + '<param name="movie" value="' + swf + '" />' + '<param name="wmode" value="transparent" />' + '<param name="allowscriptaccess" value="always" />' + "</object>";

                    container.html(html);
                })($wrap);

                // 压根就没有安转。
            } else {
                $wrap.html('<a href="http://www.adobe.com/go/getflashplayer" target="_blank" border="0"><img alt="get flash player" src="http://www.adobe.com/macromedia/style_guide/images/160x41_Get_Flash_Player.jpg" /></a>');
            }

            return;
        } else if (!WebUploader.Uploader.support()) {
            alert("Web Uploader 不支持您的浏览器！");
            return;
        }

        // 实例化
        uploader = WebUploader.create({
            pick: {
                id: "#filePicker",
                label: "点击或拖动图片",
            },
            formData: {
                uid: 123,
            },
            dnd: "#uploader .queueList",
            paste: "#uploader",
            swf: "../../webuploader/Uploader.swf",
            chunked: false,
            chunkSize: 512 * 1024,
            server: "/hotel/upload/" + $("#wrapper").attr("type"), // 上传
            // runtimeOrder: 'flash',

            accept: {
                title: "Images",
                extensions: "gif,jpg,jpeg,bmp,png",
                mimeTypes: "image/*",
            },

            // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候，把图片打开。
            disableGlobalDnd: true,
            fileNumLimit: 300,
            fileSizeLimit: 200 * 1024 * 1024, // 200 M
            fileSingleSizeLimit: 50 * 1024 * 1024, // 50 M
        });

        // 拖拽时不接受 js, txt 文件。
        uploader.on("dndAccept", function (items) {
            let denied = false;
            const len = items.length;
            let i = 0;
            // 修改js类型
            const unAllowed = "text/plain;application/javascript ";

            for (; i < len; i++) {
                // 如果在列表里面
                if (~unAllowed.indexOf(items[i].type)) {
                    denied = true;
                    break;
                }
            }

            return !denied;
        });

        uploader.on("dialogOpen", function () {
            console.log("here");
        });

        uploader.on("reset", function () {
            fileCount = 0;
            fileSize = 0;
            
            $(".filelist").empty().css("display", "none");
            Object.keys(percentages).forEach(key => {
                delete percentages[key];
            });
            setState("pedding");
            updateTotalProgress();
        });

        uploader.on("uploadSuccess", function (file, response) {
            if (typeof photoPath == "object") {
                photoPath.push(response.data);
            }
        });

        uploader.on("uploadFinished", function () {
            if (typeof callback == "function") {
                stats = uploader.getStats();
                if (stats.successNum == 0) {
                    alert("没有图片上传成功，请重试！");
                    return;
                }
                if (stats.uploadFailNum && confirm("有" + stats.uploadFailNum + "张图片上传失败，是否提交照片？")) {
                    callback(false);
                } else {
                    callback(true);
                }
            }
        });

        // 添加“添加文件”的按钮，
        uploader.addButton({
            id: "#filePicker2",
            label: "继续添加",
        });

        uploader.on("ready", function () {
            window.uploader = uploader;
        });

        // 当有文件添加进来时执行，负责view的创建
        function addFile(file) {
            const $li = $('<li id="' + file.id + '">' + '<p class="title">' + file.name + "</p>" + '<p class="imgWrap"></p>' + '<p class="progress"><span></span></p>' + "</li>");

            const $btns = $('<div class="file-panel">' + '<span class="cancel">删除</span>' + '<span class="rotateRight">向右旋转</span>' + '<span class="rotateLeft">向左旋转</span></div>').appendTo($li);
            const $prgress = $li.find("p.progress span");
            const $wrap = $li.find("p.imgWrap");
            const $info = $('<p class="error"></p>');

            const showError = function (code) {
                switch (code) {
                    case "exceed_size":
                        text = "文件大小超出";
                        break;

                    case "interrupt":
                        text = "上传暂停";
                        break;

                    default:
                        text = "上传失败，请重试";
                        break;
                }

                $info.text(text).appendTo($li);
            };

            if (file.getStatus() === "invalid") {
                showError(file.statusText);
            } else {
                // @todo lazyload
                $wrap.text("预览中");
                uploader.makeThumb(
                    file,
                    function (error, src) {
                        let img;

                        if (error) {
                            $wrap.text("不能预览");
                            return;
                        }

                        if (isSupportBase64) {
                            img = $('<img src="' + src + '">');
                            $wrap.empty().append(img);
                        } else {
                            $.ajax("../../server/preview.php", {
                                method: "POST",
                                data: src,
                                dataType: "json",
                            }).done(function (response) {
                                if (response.result) {
                                    img = $('<img src="' + response.result + '">');
                                    $wrap.empty().append(img);
                                } else {
                                    $wrap.text("预览出错");
                                }
                            });
                        }
                    },
                    thumbnailWidth,
                    thumbnailHeight
                );

                percentages[file.id] = [file.size, 0];
                file.rotation = 0;
            }

            file.on("statuschange", function (cur, prev) {
                if (prev === "progress") {
                    $prgress.hide().width(0);
                } else if (prev === "queued") {
                    $li.off("mouseenter mouseleave");
                    $btns.remove();
                }

                // 成功
                if (cur === "error" || cur === "invalid") {
                    console.log(file.statusText);
                    showError(file.statusText);
                    percentages[file.id][1] = 1;
                } else if (cur === "interrupt") {
                    showError("interrupt");
                } else if (cur === "queued") {
                    $info.remove();
                    $prgress.css("display", "block");
                    percentages[file.id][1] = 0;
                } else if (cur === "progress") {
                    $info.remove();
                    $prgress.css("display", "block");
                } else if (cur === "complete") {
                    $prgress.hide().width(0);
                    $li.append('<span class="success"></span>');
                }

                $li.removeClass("state-" + prev).addClass("state-" + cur);
            });

            $li.on("mouseenter", function () {
                $btns.stop().animate({ height: 30 });
            });

            $li.on("mouseleave", function () {
                $btns.stop().animate({ height: 0 });
            });

            $btns.on("click", "span", function () {
                const index = $(this).index();
                let deg;

                switch (index) {
                    case 0:
                        uploader.removeFile(file);
                        return;

                    case 1:
                        file.rotation += 90;
                        break;

                    case 2:
                        file.rotation -= 90;
                        break;
                }

                if (supportTransition) {
                    deg = "rotate(" + file.rotation + "deg)";
                    $wrap.css({
                        "-webkit-transform": deg,
                        "-mos-transform": deg,
                        "-o-transform": deg,
                        transform: deg,
                    });
                } else {
                    $wrap.css("filter", "progid:DXImageTransform.Microsoft.BasicImage(rotation=" + (~~(((file.rotation / 90) % 4) + 4) % 4) + ")");
                    // use jquery animate to rotation
                    // $({
                    //     rotation: rotation
                    // }).animate({
                    //     rotation: file.rotation
                    // }, {
                    //     easing: 'linear',
                    //     step: function( now ) {
                    //         now = now * Math.PI / 180;

                    //         var cos = Math.cos( now ),
                    //             sin = Math.sin( now );

                    //         $wrap.css( 'filter', "progid:DXImageTransform.Microsoft.Matrix(M11=" + cos + ",M12=" + (-sin) + ",M21=" + sin + ",M22=" + cos + ",SizingMethod='auto expand')");
                    //     }
                    // });
                }
            });

            $li.appendTo($queue);
        }

        // 负责view的销毁
        function removeFile(file) {
            const $li = $("#" + file.id);

            delete percentages[file.id];
            updateTotalProgress();
            $li.off().find(".file-panel").off().end().remove();
        }

        function updateTotalProgress() {
            let loaded = 0;
            let total = 0;
            const spans = $progress.children();
            let percent;

            $.each(percentages, function (k, v) {
                total += v[0];
                loaded += v[0] * v[1];
            });

            percent = total ? loaded / total : 0;

            spans.eq(0).text(Math.round(percent * 100) + "%");
            spans.eq(1).css("width", Math.round(percent * 100) + "%");
            updateStatus();
        }

        function updateStatus() {
            let text = "";
            let stats;

            if (state === "ready") {
                text = "选中" + fileCount + "张图片，共" + WebUploader.formatSize(fileSize) + "。";
            } else if (state === "confirm") {
                stats = uploader.getStats();
                if (stats.uploadFailNum) {
                    text = "已成功上传" + stats.successNum + "张照片，" + stats.uploadFailNum + '张照片上传失败，<a class="retry" href="#">重新上传</a>或<a class="ignore" href="#">忽略</a>';
                }
            } else {
                stats = uploader.getStats();
                text = "共" + fileCount + "张（" + WebUploader.formatSize(fileSize) + "），已上传" + stats.successNum + "张";

                if (stats.uploadFailNum) {
                    text += "，失败" + stats.uploadFailNum + "张";
                }
            }

            $info.html(text);
        }

        function setState(val) {
            let file;
            let stats;

            if (val === state) {
                return;
            }

            $upload.removeClass("state-" + state);
            $upload.addClass("state-" + val);
            state = val;

            switch (state) {
                case "pedding":
                    $placeHolder.removeClass("element-invisible");
                    $queue.hide();
                    $statusBar.addClass("element-invisible");
                    uploader.refresh();
                    break;

                case "ready":
                    $placeHolder.addClass("element-invisible");
                    $("#filePicker2").removeClass("element-invisible");
                    $queue.show();
                    $statusBar.removeClass("element-invisible");
                    uploader.refresh();
                    break;

                case "uploading":
                    $("#filePicker2").addClass("element-invisible");
                    $progress.show();
                    $upload.text("暂停上传");
                    break;

                case "paused":
                    $progress.show();
                    $upload.text("继续上传");
                    break;

                case "confirm":
                    $progress.hide();
                    $("#filePicker2").removeClass("element-invisible");
                    $upload.text("开始上传");

                    stats = uploader.getStats();
                    if (stats.successNum && !stats.uploadFailNum) {
                        setState("finish");
                        return;
                    }
                    break;
                case "finish":
                    stats = uploader.getStats();
                    if (stats.successNum) {
                        // alert("上传成功");
                    } else {
                        // 没有成功的图片，重设
                        alert("所有照片上传失败，请重试！");
                        state = "done";
                        location.reload();
                    }
                    break;
            }

            updateStatus();
        }

        uploader.onUploadProgress = function (file, percentage) {
            const $li = $("#" + file.id);
            const $percent = $li.find(".progress span");

            $percent.css("width", percentage * 100 + "%");
            percentages[file.id][1] = percentage;
            updateTotalProgress();
        };

        uploader.onFileQueued = function (file) {
            fileCount++;
            fileSize += file.size;

            if (fileCount === 1) {
                $placeHolder.addClass("element-invisible");
                $statusBar.show();
            }

            addFile(file);
            setState("ready");
            updateTotalProgress();
        };

        uploader.onFileDequeued = function (file) {
            fileCount--;
            fileSize -= file.size;

            if (!fileCount) {
                setState("pedding");
            }

            removeFile(file);
            updateTotalProgress();
        };

        uploader.on("all", function (type) {
            let stats;
            switch (type) {
                case "uploadFinished":
                    setState("confirm");
                    break;

                case "startUpload":
                    setState("uploading");
                    break;

                case "stopUpload":
                    setState("paused");
                    break;
            }
        });

        uploader.onError = function (code) {
            alert("Eroor: " + code);
        };

        $upload.on("click", function () {
            if ($(this).hasClass("disabled")) {
                return false;
            }

            if (state === "ready") {
                uploader.upload();
            } else if (state === "paused") {
                uploader.upload();
            } else if (state === "uploading") {
                uploader.stop();
            }
        });

        $info.on("click", ".retry", function () {
            uploader.retry();
        });

        $info.on("click", ".ignore", function () {
            alert("todo");
        });

        $upload.addClass("state-" + state);
        updateTotalProgress();
    });
})(jQuery);
